#include "led.h"

#define LED_PIN 5
#define LED_NUM 144

static const char *TAG = "led";

rmt_channel_handle_t led_chan = NULL;
rmt_tx_channel_config_t tx_chan_config;

rmt_encoder_handle_t led_encoder = NULL;
rmt_transmit_config_t tx_config;

static uint8_t led_strip_pixels[LED_NUM * 3];
static uint8_t led_strip_pixels_2[LED_NUM * 3];

void hsv_to_reb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b)
{
    h %= 360; // h -> [0,360]
    uint32_t rgb_max = v * 2.55f;
    uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;

    uint32_t i = h / 60;
    uint32_t diff = h % 60;

    // RGB adjustment amount by hue
    uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;

    switch (i)
    {
    case 0:
        *r = rgb_max;
        *g = rgb_min + rgb_adj;
        *b = rgb_min;
        break;
    case 1:
        *r = rgb_max - rgb_adj;
        *g = rgb_max;
        *b = rgb_min;
        break;
    case 2:
        *r = rgb_min;
        *g = rgb_max;
        *b = rgb_min + rgb_adj;
        break;
    case 3:
        *r = rgb_min;
        *g = rgb_max - rgb_adj;
        *b = rgb_max;
        break;
    case 4:
        *r = rgb_min + rgb_adj;
        *g = rgb_min;
        *b = rgb_max;
        break;
    default:
        *r = rgb_max;
        *g = rgb_min;
        *b = rgb_max - rgb_adj;
        break;
    }
}

void led_init(void)
{
    ESP_LOGI(TAG, "Create rmt tx channnel");

    tx_chan_config.clk_src = RMT_CLK_SRC_DEFAULT; // 时钟源
    tx_chan_config.gpio_num = LED_PIN;            // gpio引脚
    tx_chan_config.mem_block_symbols = 64;        // 分配的内存大小
    tx_chan_config.resolution_hz = 10000000;      // 时钟频率
    tx_chan_config.trans_queue_depth = 4;         // 队列大小

    ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));

    ESP_LOGI(TAG, "Install led strip encoder");

    led_strip_encoder_config_t encoder_config = {
        .resolution = 10000000,
    };

    ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));
    ESP_LOGI(TAG, "Enable RMT TX channel");
    ESP_ERROR_CHECK(rmt_enable(led_chan));

    ESP_LOGI(TAG, "Start LED rainbow chase");
    tx_config.loop_count = 0;

    led_set_all_hsv(100,100,10);
    memcpy(led_strip_pixels_2,led_strip_pixels,sizeof(led_strip_pixels));
}

void led_point_set_rgb(uint16_t point, uint32_t r, uint32_t g, uint32_t b)
{
    if (point < 1)
    {
        ESP_LOGE(TAG, "led point < 1");
        point = 1;
    }
    point--;
    led_strip_pixels[point * 3 + 0] = g;
    led_strip_pixels[point * 3 + 1] = r;
    led_strip_pixels[point * 3 + 2] = b;
}

void led_point_set_hsv(uint16_t point, uint32_t h, uint32_t s, uint32_t v)
{
    uint32_t r, g, b;
    hsv_to_reb(h, s, v, &r, &g, &b);
    if (point < 1)
    {
        ESP_LOGE(TAG, "led point < 1");
        point = 1;
    }
    point--;
    led_strip_pixels[point * 3 + 0] = g;
    led_strip_pixels[point * 3 + 1] = b;
    led_strip_pixels[point * 3 + 2] = r;
}

void led_set_all_rgb(uint32_t r, uint32_t g, uint32_t b)
{
    for (int i = 0; i < LED_NUM; i++)
    {
        led_strip_pixels[i * 3 + 0] = g;
        led_strip_pixels[i * 3 + 1] = b;
        led_strip_pixels[i * 3 + 2] = r;
    }
}

void led_set_all_hsv(uint32_t h, uint32_t s, uint32_t v)
{
    uint32_t r, g, b;
    hsv_to_reb(h, s, v, &r, &g, &b);
    for (int i = 0; i < LED_NUM; i++)
    {
        led_strip_pixels[i * 3 + 0] = g;
        led_strip_pixels[i * 3 + 1] = b;
        led_strip_pixels[i * 3 + 2] = r;
    }
}

void led_refresh(void)
{
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}

void led_off(void)
{
    // for(int i = 0; i < LED_NUM; i++)
    // {
    //     led_strip_pixels[i] = 0;
    // }
    memcpy(led_strip_pixels_2, led_strip_pixels, sizeof(led_strip_pixels));
    memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
    // led_refresh();
}

void led_on(void)
{
    memcpy(led_strip_pixels, led_strip_pixels_2, sizeof(led_strip_pixels));
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}

void disp_menu(uint8_t first, uint8_t second, uint8_t last)
{
    if((first == 1)&&(second == 0)&&(last == 0))//色相设置界面
    {
        for(int i = 1; i < 49; i++)
        {
            led_point_set_rgb(i,0x40,0x00,0x00);
        }
        for(int i = 49; i < 97; i++)
        {
            led_point_set_rgb(i,0x00,0x10,0x00);
        }
        for(int i = 97; i < 145; i++)
        {
            led_point_set_rgb(i,0x00,0x00,0x10);
        }
    }
    if((first == 2)&&(second == 0)&&(last == 0))//饱和度设置界面
    {
        for(int i = 0; i < 48; i++)
        {
            led_point_set_rgb(i,0x10,0x00,0x00);
        }
        for(int i = 48; i < 96; i++)
        {
            led_point_set_rgb(i,0x00,0x40,0x00);
        }
        for(int i = 96; i < 144; i++)
        {
            led_point_set_rgb(i,0x00,0x00,0x10);
        }
    }
    if((first == 3)&&(second == 0)&&(last == 0))//亮度设置界面
    {
        for(int i = 0; i < 48; i++)
        {
            led_point_set_rgb(i,0x10,0x00,0x00);
        }
        for(int i = 48; i < 96; i++)
        {
            led_point_set_rgb(i,0x00,0x10,0x00);
        }
        for(int i = 96; i < 144; i++)
        {
            led_point_set_rgb(i,0x00,0x00,0x40);
        }
    }
}